{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "8af9293c-875c-49b8-e46f-2df28e416530",
        "id": "Kc1utwUgGOoq"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "原始数据维度: (10, 6)\n",
            "原始数据:\n",
            " [[2.1 5.6 3.2 8.9 1.5 6.3]\n",
            " [4.7 2.3 9.1 5.4 7.8 3.6]\n",
            " [1.9 8.2 4.5 2.7 6.1 9.4]\n",
            " [7.3 3.5 1.2 6.8 4.9 2.1]\n",
            " [5.5 1.8 7.6 3.3 9.2 5.7]\n",
            " [3.8 6.9 2.4 9.5 3.1 7.8]\n",
            " [6.2 4.1 8.3 1.9 5.4 4.3]\n",
            " [8.4 7.5 5.9 4.6 2.8 1.2]\n",
            " [2.6 9.3 6.7 7.2 8.5 6.9]\n",
            " [9.1 2.9 3.8 5.1 1.7 8.6]]\n",
            "\n",
            "中心化后的数据:\n",
            " [[-3.06  0.39 -2.07  3.36 -3.6   0.71]\n",
            " [-0.46 -2.91  3.83 -0.14  2.7  -1.99]\n",
            " [-3.26  2.99 -0.77 -2.84  1.    3.81]\n",
            " [ 2.14 -1.71 -4.07  1.26 -0.2  -3.49]\n",
            " [ 0.34 -3.41  2.33 -2.24  4.1   0.11]\n",
            " [-1.36  1.69 -2.87  3.96 -2.    2.21]\n",
            " [ 1.04 -1.11  3.03 -3.64  0.3  -1.29]\n",
            " [ 3.24  2.29  0.63 -0.94 -2.3  -4.39]\n",
            " [-2.56  4.09  1.43  1.66  3.4   1.31]\n",
            " [ 3.94 -2.31 -1.47 -0.44 -3.4   3.01]]\n",
            "\n",
            "协方差矩阵维度: (6, 6)\n",
            "协方差矩阵:\n",
            " [[ 6.71155556 -3.33622222 -0.13244444 -1.91377778 -2.11555556 -3.46377778]\n",
            " [-3.33622222  7.05655556 -1.41855556  1.67733333 -0.79222222  1.84122222]\n",
            " [-0.13244444 -1.41855556  7.06233333 -3.95755556  4.71666667 -1.45922222]\n",
            " [-1.91377778  1.67733333 -3.95755556  6.52711111 -2.71777778  0.62488889]\n",
            " [-2.11555556 -0.79222222  4.71666667 -2.71777778  7.84444444 -0.38444444]\n",
            " [-3.46377778  1.84122222 -1.45922222  0.62488889 -0.38444444  7.52988889]]\n",
            "\n",
            "降维到 2 维后的数据维度: (10, 2)\n",
            "降维到 2 维后的数据:\n",
            " [[ 5.401895    0.2162004 ]\n",
            " [-4.91467967 -0.78289549]\n",
            " [ 1.61117506 -5.13347398]\n",
            " [ 0.70798736  4.69243334]\n",
            " [-5.43805528 -1.41354288]\n",
            " [ 5.94375261 -0.36345365]\n",
            " [-4.54361192  0.37727419]\n",
            " [-1.0408181   3.9409491 ]\n",
            " [ 0.92959079 -5.52223167]\n",
            " [ 1.34276415  3.98874065]]\n",
            "\n",
            "保留的方差百分比: 67.34%\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "# 1. 使用指定的4个6维数据样本\n",
        "a = np.array([\n",
        " [2.1, 5.6, 3.2, 8.9, 1.5, 6.3],\n",
        " [4.7, 2.3, 9.1, 5.4, 7.8, 3.6],\n",
        " [1.9, 8.2, 4.5, 2.7, 6.1, 9.4],\n",
        " [7.3, 3.5, 1.2, 6.8, 4.9, 2.1],\n",
        " [5.5, 1.8, 7.6, 3.3, 9.2, 5.7],\n",
        " [3.8, 6.9, 2.4, 9.5, 3.1, 7.8],\n",
        " [6.2, 4.1, 8.3, 1.9, 5.4, 4.3],\n",
        " [8.4, 7.5, 5.9, 4.6, 2.8, 1.2],\n",
        " [2.6, 9.3, 6.7, 7.2, 8.5, 6.9],\n",
        " [9.1, 2.9, 3.8, 5.1, 1.7, 8.6]\n",
        "])\n",
        "print(\"原始数据维度:\", a.shape)       # a: 原始数据\n",
        "print(\"原始数据:\\n\", a)\n",
        "\n",
        "# 2. PCA处理降维\n",
        "\n",
        "# 2.1 数据标准化 (中心化)\n",
        "b = np.mean(a, axis=0)          # b: 每一列的均值\n",
        "c = a - b # c: 中心化后的数据\n",
        "print(\"\\n中心化后的数据:\\n\", c)\n",
        "\n",
        "# 2.2 计算协方差矩阵\n",
        "d = np.cov(c.T) # d: 协方差矩阵\n",
        "print(\"\\n协方差矩阵维度:\", d.shape)\n",
        "print(\"协方差矩阵:\\n\", d)\n",
        "\n",
        "# 2.3 计算特征值和特征向量\n",
        "e, f = np.linalg.eig(d)          # e: 特征值, f: 特征向量\n",
        "\n",
        "# 2.3.1 检查特征值非负性\n",
        "if np.any(e < 0):\n",
        "    print(\"警告: 存在负特征值，协方差矩阵可能不是半正定的。\")\n",
        "\n",
        "\n",
        "# 2.4 对特征值进行排序，并取出对应的特征向量 (降序)\n",
        "g = np.argsort(e)[::-1]           # g: 特征值排序后的索引\n",
        "h = e[g]                  # h: 排序后的特征值\n",
        "i = f[:, g]                # i: 排序后的特征向量\n",
        "\n",
        "# 2.5 选择主成分 (这里选择前两个主成分进行降维到2维为例)\n",
        "k = 2                   # k: 选择的主成分数量\n",
        "l = i[:, :k]               # l: 选择的主成分 (特征向量)\n",
        "\n",
        "# 2.6 将原始数据投影到主成分上\n",
        "m = np.dot(c, l)             # m: 降维后的数据\n",
        "print(f\"\\n降维到 {k} 维后的数据维度:\", m.shape)\n",
        "print(f\"降维到 {k} 维后的数据:\\n\", m)\n",
        "\n",
        "# 3. 计算保留的方差百分比\n",
        "n = h[:k] / np.sum(h)          # n: 每个选择的主成分的方差贡献率\n",
        "o = np.sum(n)               # o: 保留的总方差百分比\n",
        "print(f\"\\n保留的方差百分比: {o * 100:.2f}%\")"
      ]
    }
  ]
}